package com.example.single;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @author houyangfan
 * @version 1.0
 * @date 2022/10/4 22:25
 * <p>
 * 懒汉式 ： 只有在用的时候才创建，但是这里要注意线程安全问题
 */
public class LazySingle {

    private LazySingle() {
        System.out.println(Thread.currentThread().getName());
    }

    private volatile static LazySingle single;

    // 双重检测锁模式的 懒汉式单例--》 DCL单例模式
    public static LazySingle getInstance() {
        if (single == null) {
            synchronized (LazySingle.class) {
                if (single == null) {
                    // 创建对象的过程不是原子性操作
                    /**
                     * 1. 分配内存空间
                     * 2. 执行构造方法初始化对象
                     * 3. 把这个对象指向这个空间
                     *
                     * 内存里的操作顺序可能为123 也可能为132,所以可能导致，第一个线程还未创建对象，但是先
                     * 把这个对象引用指向了这个空间，然后第二个线程进来后判断对象因为不为null
                     */
                    single = new LazySingle();
                }
            }
        }
        return single;
    }

    public static void main(String[] args) throws Exception{

        /*for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                LazySingle instance = LazySingle.getInstance();
            }).start();
        }*/

        LazySingle instance = LazySingle.getInstance();
        Constructor<LazySingle> declaredConstructor = LazySingle.class.getDeclaredConstructor();
        declaredConstructor.setAccessible(true);
        LazySingle single1 = declaredConstructor.newInstance();
        System.out.println(instance);
        System.out.println(single1);
    }
}
